home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / AppInstall / widgets / AppListView.py < prev    next >
Encoding:
Python Source  |  2009-03-31  |  7.8 KB  |  202 lines

  1. import pango
  2. import gtk
  3. import gobject
  4. (COL_CAT_NAME,
  5.  COL_CAT_ITEM) = range(0,2)
  6.  
  7. from gettext import gettext as _
  8. from math import log
  9. from xml.sax.saxutils import escape
  10.  
  11. def xmlescape(s):
  12.     if s==None:
  13.         return ""
  14.     else:
  15.         return escape(s)
  16.  
  17. # Columns of the packages store
  18. (COL_NAME,
  19.  COL_ITEM,
  20.  COL_POPCON) = range(3)
  21.  
  22. (STYLE_ALL, STYLE_DESC, STYLE_INSTALL) = range(3)
  23.  
  24. class AppListView(gtk.TreeView, gobject.GObject):
  25.     __gsignals__ = {"toggled":(gobject.SIGNAL_RUN_FIRST,
  26.                                gobject.TYPE_NONE,
  27.                                (gobject.TYPE_PYOBJECT,))}
  28.     def __init__(self, cache=None, menu=None, icons=None, style=STYLE_ALL):
  29.         self.cache = cache
  30.         self.menu = menu
  31.  
  32.         self.desc_cache = {}
  33.  
  34.         self.__gobject_init__()
  35.         gtk.TreeView.__init__(self)
  36.         self.set_rules_hint(True)
  37.         if icons == None:
  38.             self.icons = gtk.icon_theme_get_default()
  39.         else:
  40.             self.icons = icons
  41.         # Add a fake liststore to the packages list, so that the headers
  42.         # are already seen during start up
  43.         fake_applications = gtk.ListStore(gobject.TYPE_INT,
  44.                                           gobject.TYPE_STRING,
  45.                                           gobject.TYPE_PYOBJECT,
  46.                                           gobject.TYPE_INT)
  47.         fake_applications.set_sort_column_id(COL_NAME, gtk.SORT_ASCENDING)
  48.         self.set_model(fake_applications)
  49.  
  50.         self.stars = self._get_stars()
  51.  
  52.         # popcon renderer
  53.         renderer_popcon = gtk.CellRendererPixbuf()
  54.         renderer_popcon.set_property("xpad", 4)
  55.         column_app_popcon = gtk.TreeViewColumn(_("Popularity"), 
  56.                                                renderer_popcon)
  57.         column_app_popcon.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
  58.         column_app_popcon.set_sort_column_id(COL_POPCON)
  59.         column_app_popcon.set_cell_data_func(renderer_popcon, 
  60.                                              self._popcon_view_func)
  61.         column_app_popcon.set_fixed_width(108)
  62.         self.column_app_popcon = column_app_popcon
  63.  
  64.         # check boxes
  65.         renderer_status = gtk.CellRendererToggle()
  66.         renderer_status.connect('toggled', self._on_toggled)
  67.         renderer_status.set_property("xalign", 0.5)
  68.         renderer_status.set_property("yalign", 0.5)
  69.         column_app_status = gtk.TreeViewColumn("")
  70.         column_app_status.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
  71.         column_app_status.pack_start(renderer_status, False)
  72.         column_app_status.set_cell_data_func (renderer_status, 
  73.                                               self._toggle_cell_func)
  74.         # FIXME: we need to react on theme changes
  75.         width = renderer_status.get_size(self)[2] + 8
  76.         column_app_status.set_fixed_width(width)
  77.  
  78.         # Application column (icon, name, description)
  79.         column_app = gtk.TreeViewColumn(_("Application"))
  80.         column_app.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
  81.         column_app.set_expand(True)
  82.         column_app.set_sort_column_id(COL_NAME)
  83.         # The icon
  84.         renderer_app_icon = gtk.CellRendererPixbuf()
  85.         column_app.pack_start(renderer_app_icon, False)
  86.         column_app.set_cell_data_func(renderer_app_icon, 
  87.                                       self._icon_cell_func)
  88.         # app name and description
  89.         renderer_app = gtk.CellRendererText()
  90.         renderer_app.set_property("ellipsize", pango.ELLIPSIZE_END)
  91.         column_app.pack_start(renderer_app, True)
  92.         column_app.set_cell_data_func(renderer_app, 
  93.                                       self._package_view_func)
  94.  
  95.         if style == STYLE_ALL:
  96.             self.append_column(column_app_status)
  97.             self.append_column(column_app)
  98.             self.append_column(column_app_popcon)
  99.         elif style == STYLE_DESC:
  100.             self.append_column(column_app)
  101.         elif style == STYLE_INSTALL:
  102.             self.append_column(column_app_status)
  103.             self.append_column(column_app)
  104.  
  105.         self.set_fixed_height_mode(True)
  106.  
  107.     def hook(self, cache, menu):
  108.         self.cache = cache
  109.         self.menu = menu
  110.  
  111.     def _get_stars(self):
  112.         """
  113.         Return a prerendered list of rating stars pixbufs
  114.         """
  115.         stars = []
  116.         try:
  117.             pixbuf_star = self.icons.load_icon("gnome-app-install-star", 16, 0)
  118.         except gobject.GError:
  119.             pixbuf_star = self.icons.load_icon(gtk.STOCK_MISSING_IMAGE, 16, 0)
  120.         for i in range(5):
  121.             starlets = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True,
  122.                                      8, 96, 16) # depth, width, height
  123.             starlets.fill(0x0)
  124.             for l in range(i+1):
  125.                 pixbuf_star.copy_area(0,0,        # from
  126.                                       16,16,      # size
  127.                                       starlets,   # to-pixbuf
  128.                                       20 * l, 0)  # dest
  129.             stars.append(starlets)
  130.         return stars
  131.  
  132.     def _popcon_view_func(self, cell_layout, renderer, model, iter):
  133.         """
  134.         Create a pixmap showing a row of stars representing the popularity
  135.         of the corresponding application
  136.         """
  137.         (name, item, popcon) = model[iter]
  138.         rank = 0
  139.         if item.popcon > 0:
  140.             rank = int(5 * log(item.popcon) / log(self.menu.popcon_max + 1))
  141.         renderer.set_property("pixbuf", self.stars[rank])
  142.  
  143.     def _package_view_func(self, cell_layout, renderer, model, iter):
  144.         app = model.get_value(iter, COL_ITEM)
  145.         app_name = model.get_value(iter, COL_NAME)
  146.         if self.desc_cache.has_key(app_name):
  147.             (name, desc) = self.desc_cache[app_name]
  148.         else:
  149.             name = xmlescape(app.desktop_entry.getName())
  150.             desc = xmlescape(app.desktop_entry.getComment())
  151.             # KDE stores the comment in the GerneicName
  152.             if desc == "":
  153.                 desc = xmlescape(app.desktop_entry.get('GenericName'))
  154.             self.desc_cache[app_name] = (name, desc)
  155.         if self.menu:
  156.             future = app.toInstall
  157.             current = self.menu.itemIsInstalled(app)
  158.         else:
  159.             future = None
  160.             current = None
  161.  
  162.         if current != future:
  163.             markup = "<b>%s</b>\n<small><b>%s</b></small>" % (name, desc)
  164.         else:
  165.             markup = "%s\n<small>%s</small>" % (name, desc)
  166.         renderer.set_property("markup", markup)
  167.  
  168.     def _toggle_cell_func(self, column, cell, model, iter):
  169.         menuitem = model.get_value(iter, COL_ITEM)
  170.         cell.set_property("active", menuitem.toInstall)
  171.         if menuitem.architectures and \
  172.            self.cache.getArch() not in menuitem.architectures:
  173.             cell.set_property("activatable", False)
  174.         else:
  175.             cell.set_property("activatable", True)
  176.  
  177.     def _icon_cell_func(self, column, cell, model, iter):
  178.         menuitem = model.get_value(iter, COL_ITEM)
  179.         if menuitem == None or menuitem.iconname == None:
  180.             cell.set_property("pixbuf", None)
  181.             cell.set_property("visible", False)
  182.             return
  183.         try:
  184.             icon = self.icons.load_icon(menuitem.iconname, 24, 0)
  185.             # work around bug #209072 even if we ask for a 24px
  186.             # icon, we sometimes get outrages big ones - 256x256
  187.             if icon and (icon.get_height() > 24 or icon.get_width() > 24):
  188.                 #print "WARNING: scaling down ", menuitem.iconname
  189.                 icon = icon.scale_simple(24,24,gtk.gdk.INTERP_BILINEAR)
  190.         except gobject.GError:
  191.             try:
  192.                 icon = self.icons.load_icon("applications-other", 24, 0)
  193.             except gobject.GError:
  194.                 icon = self.icons.load_icon(gtk.STOCK_MISSING_IMAGE, 24, 0)
  195.         cell.set_property("pixbuf", icon)
  196.         cell.set_property("visible", True)
  197.  
  198.     def _on_toggled(self, widget, path):
  199.         model = self.get_model()
  200.         (name, item, popcon) = model[path]
  201.         self.emit("toggled", item)
  202.